use tokio_util::codec::Decoder;
use bytes::{ BytesMut};
use std::{fmt, io, ops::Index, usize};
use std::sync::Arc;
use futures_util::future::ok;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::TcpStream;
use tokio_util::bytes::Buf;
use crate::decode::analyze::{Analyze, IJtRtpHead, JtRtpHeadv13};
use crate::encode::broker::Broker;

const HEAD1078: [u8; 4] = [0x30, 0x31, 0x63, 0x64];
#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct Jt1078Codec {
    /// 手机号长度(10Byte or 6Byte 为0时表示自动预测 自动预测时至少需要收1个完整包和下一个包的包头)
    sim_len: usize,
    /// 是否已找到头
    // find_head: bool,
    // /// 包大小(19协议,13协议)
    // now_package_size: Option<usize>,
    /// 已结束
    eof: bool,
    sim: String,
    channel:u8,
}
impl Jt1078Codec {
    pub fn new() -> Self {
        Jt1078Codec {
            sim_len: 0,
            // find_head: false,
            // now_package_size: None,
            eof: false,
            sim:String::new(),
            channel:0,
        }
    }

    pub async fn handle_connection(&mut self, mut socket:TcpStream,  broker: Arc<Broker>) {
        let mut buffer = BytesMut::with_capacity(1024*100);
        loop {
            let _=match socket.read_buf( &mut buffer).await {
                Ok(..) => match self.decode_eof( &mut buffer) {
                    Ok(Some(jt)) => {
                        let topic=format!("{}-{}",self.sim,self.channel);
                        broker.produce(topic,jt.data).await;
                    }
                    Ok(None) => {}
                    Err(e) => {
                        println!("解码异常原因如下: {}", e);
                        let _ = socket.shutdown();
                        break;
                    }
                },
                Err(e) => { println!("连接读取异常: {}", e); return; }
            };
        }
    }
    // version 0=sim12 其他=sim20
    fn decode_packet(buf: &mut BytesMut, version: usize) -> Result<Option<Analyze>, Jt1078CodecError> {
        //数据类型下标
        let data_type_index = match version {
            0 => 15, //28,
            _ => 19,//32
        };
        //数据类型
        let data_type = (*buf.index(data_type_index)  >> 4) & 0x0F;
        //数据长度下标
        let data_len_index = match data_type {
            0 => data_type_index + 13, //28,
            1 => data_type_index + 13,
            2 => data_type_index + 13,
            3 => data_type_index + 9, //24,
            _ => data_type_index + 1, // 16,
        };
        //数据长度
        let data_len = match buf.chunk().get(data_len_index..data_len_index + 2) {
            Some(src) => unsafe {u16::from_be_bytes(*(src as *const _ as *const [_; 2])) as usize},
            None => {return Ok(None);}
        };
        let next_start = data_len_index + data_len+ 2 ;
        if buf.len() < next_start + 4 {return Ok(None);}
        if buf[next_start..next_start + 4].eq(&HEAD1078) {
            match version {
                0 => {
                    //let rtp=JtRtpHeadv13::new();
                    let rtp=Analyze::analyze16(Some(buf.split_to(next_start).freeze()).unwrap()).unwrap();
                    Ok(Some(rtp))
                     // Ok(Some())
                }
                _ => {
                    Ok(Some(Analyze::analyze19(Some(buf.split_to(next_start).freeze()).unwrap()).unwrap()))
                }
            }
        } else {
            return Err(Jt1078CodecError::No1078);
        }
    }

}
impl Decoder for Jt1078Codec {
    type Item = Analyze;
    type Error = Jt1078CodecError;
    fn decode(&mut self, buf: &mut BytesMut) -> Result<Option<Self::Item>, Jt1078CodecError> {
        if buf.len() < self.sim_len + 12 {
            return Ok(None);
        }
        if !buf[..4].eq(&HEAD1078) {
            return Err(Jt1078CodecError::No1078);
        }
        if self.sim_len == 0 {
            //尝试2013
            let jt13 = Self::decode_packet(buf, 0);
            if let Ok(Some(ret)) = jt13 {
                //let jt_data=ret.clone();
                self.sim=ret.sim_card_number.clone();
                self.channel=ret.channel_number;
                self.sim_len = 6;
                println!("{}-{}设备开始输出", self.sim, self.channel);
                return Ok(Some(ret));
            }
            //尝试2019
            let jt19 = Self::decode_packet(buf, 1 );
            if let Ok(Some(ret)) = jt19 {
                let jt_data=ret.clone();
                self.sim=jt_data.sim_card_number;
                self.channel=ret.channel_number;
                self.sim_len = 10;
                println!("{}-{}设备开始输出", self.sim, self.channel);
                return Ok(Some(ret));
            }
            if jt13.is_err() && jt13.is_err() {
                return Err(Jt1078CodecError::No1078);
            }
        }
        else if self.sim_len == 6 {
            return Self::decode_packet(buf, 0);
        } else if self.sim_len == 10 {
            return Self::decode_packet(buf, 1);
        }
        Ok(None)
    }

    fn decode_eof(&mut self, buf: &mut BytesMut) -> Result<Option<Self::Item>, Jt1078CodecError> {
        self.eof = true;
        match self.decode(buf)? {
            Some(frame) => {
                Ok(Some(frame))
            },
            None => {
                Ok(None)
            }
        }
    }
}

#[derive(Debug)]
pub enum Jt1078CodecError {
    /// An IO error occurred.
    Io(io::Error),
    /// 非1078封包格式
    No1078,
}
impl fmt::Display for Jt1078CodecError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Jt1078CodecError::Io(e) => write!(f, "{}", e),
            &Jt1078CodecError::No1078 => write!(f, "1078格式校验错误"),
        }
    }
}
impl From<io::Error> for Jt1078CodecError {
    fn from(e: io::Error) -> Jt1078CodecError {
        Jt1078CodecError::Io(e)
    }
}

pub trait CodecError {
    fn is_io_err(&self) -> bool;
}
//解码结束
pub trait CodecEof {
    fn is_eof(&self) -> bool;
}
impl CodecEof for Jt1078Codec {
    fn is_eof(&self) -> bool {
        self.eof
    }
}
//解码错误
impl CodecError for Jt1078CodecError {
    fn is_io_err(&self) -> bool {
        if let Self::Io(_) = self {
            return true;
        }
        return false;
    }
}